package com.tzy.note.base.thread;

import org.junit.jupiter.api.Test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author tangzanyong
 * @description 多线程实现方式四：实现Callable接口
 *  实现Callable重写call方法,实现Callable和实现Runnable类似，但是功能更强大，具体表现在
 *      1.可以在任务结束后提供一个返回值，Runnable不行
 *      2.call方法可以抛出异常，Runnable的run方法不行
 *      3.可以通过运行Callable得到的Fulture对象监听目标线程调用call方法的结果，得到返回值，（fulture.get(),调用后会阻塞，直到获取到返回值）
 * @date 2020/4/16
 **/
public class Thread4 implements Callable<String> {
    /*
    1.Callable接口介绍：
        (1) java.util.concurrent.Callable是一个泛型接口，只有一个call()方法
        (2) call()方法抛出异常Exception异常，且返回一个指定的泛型类对象
    2.Callable接口实现多线程的应用场景
        (1) 当父线程想要获取子线程的运行结果时
    3.使用Callable接口实现多线程的步骤
        (1) 第一步：创建Callable子类的实例化对象
        (2) 第二步：创建FutureTask对象，并将Callable对象传入FutureTask的构造方法中
            (注意：FutureTask实现了Runnable接口和Future接口)
        (3)第三步：实例化Thread对象，并在构造方法中传入FurureTask对象
        (4)第四步：启动线程
    */

    @Override
    public String call() throws Exception {
        String task = Thread.currentThread().getName() + "执行任务";
        System.out.println(task);
        return task + "成功";
    }

    @Test
    public void test() throws Exception{
        FutureTask<String> ft = new FutureTask<>(new Thread4());
        Thread thread = new Thread(ft);
        thread.setName("线程A");
        thread.start();//开启线程
        System.out.println("线程" + Thread.currentThread().getName() + "得到结果：" + ft.get());
    }

    @Test
    public void testAnony() throws Exception{
        // 1.创建线程任务
        Callable<Integer> call = () -> {
            System.out.println("线程任务开始执行了....");
            Thread.sleep(20000);
            return 1;
        };
        // 2.将任务封装为FutureTask
        FutureTask<Integer> task = new FutureTask<>(call);
        // 3.开启线程，执行线程任务
        new Thread(task).start();
        // ====================
        System.out.println("这里是在线程启动之后，线程结果返回之前....");
        // ====================
        // 拿到线程的执行结果后
        Integer result = task.get();
        System.out.println("主线程中拿到异步任务执行的结果为：" + result);
    }

    @Test
    public void testAnonyCallable(){
        Callable<String> cl = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println(Thread.currentThread().getName() + "正在行军~~~");
                System.out.println(Thread.currentThread().getName() + "遭遇敌军~~~");
                System.out.println(Thread.currentThread().getName() + "奋勇杀敌！！！！");
                return "战斗胜利，俘虏敌军50000人";
            }
        };
        FutureTask<String> ft = new FutureTask(cl);
        new Thread(ft, "tzy部队").start();
        try {
            Thread.currentThread().setName("tangzanyong部队");
            Thread.sleep(3000);
            System.out.println(Thread.currentThread().getName() + "休整3000ms");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "整顿完毕，等待友军消息...");
        try {
            String str = ft.get();
            System.out.println("tangzanyong部队得知友军消息为：" + str);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

}
